import {
  Body,
  Controller,
  Get,
  Injectable,
  Module,
  Put,
  UseInterceptors,
} from "@nestjs/common";
import { AdminLoginInterceptor } from "src/admin/interceptor/alogin.interceptor";
import {
  Configuration,
  writeOutConfiguration,
  loadConfiguration,
} from "src/common/configuration";
import configuration from "src/common/configuration";
import { WebResult } from "src/common/web.result";
import {
  ArticleConfigurationDTO,
  BaiduTongjiConfigurationDTO,
  ConfigurationDTO,
  EmailConfigurationDTO,
  RSSConfigurationDTO,
  TwikooConfigurationDTO,
  UserConfigurationDTO,
  WebsiteConfigurationDTO,
  WechatConfigurationDTO,
} from "./dto/configuration.dto";
import { UserModule } from "src/user/user.module";

@Injectable()
export class AdminConfigurationService {
  constructor() {}

  getConfiguration(): Configuration {
    return configuration;
  }

  mergeConfiguration(c: Partial<Configuration> | ConfigurationDTO) {
    const originalConfiguration = Object.assign({}, this.getConfiguration());

    function merge(target: Record<any, any>, nc: Record<any, any>) {
      for (const k in target) {
        if (nc[k] === undefined) {
          continue;
        }

        if (Array.isArray(target[k])) {
          target[k] = nc[k];
        } else if (typeof target[k] === "object" && typeof nc[k] === "object") {
          merge(target[k], nc[k]);
        } else {
          target[k] = nc[k];
        }
      }
      return target;
    }
    return merge(originalConfiguration, c) as Configuration;
  }
  updateConfiguration(
    newConfiguration: Partial<Configuration> | ConfigurationDTO,
  ): void | never {
    const nc = this.mergeConfiguration(newConfiguration);
    writeOutConfiguration(nc);
    loadConfiguration();
  }
}

@Controller("/admin/configuration")
@UseInterceptors(AdminLoginInterceptor)
export class AdminConfigurationController {
  constructor(
    private readonly adminConfigurationService: AdminConfigurationService,
  ) {}

  @Get()
  getConfiguration() {
    const c = this.adminConfigurationService.getConfiguration();
    return WebResult.success(c);
  }

  @Put()
  async updateConfiguration(newConfiguration: ConfigurationDTO) {
    if (newConfiguration.server) {
      delete newConfiguration.server;
    }
    if (newConfiguration.resource) {
      delete newConfiguration.resource;
    }
    try {
      this.adminConfigurationService.updateConfiguration(newConfiguration);
      return WebResult.success(undefined, "配置更新成功");
    } catch (e) {
      console.error(e);
      return WebResult.failure(undefined, "配置更新失败");
    }
  }

  @Put("/website")
  updateWebsiteConfiguration(
    @Body() newWebsiteConfiguration: WebsiteConfigurationDTO,
  ) {
    return this.updateConfiguration({
      website: newWebsiteConfiguration,
    });
  }
  @Put("/email")
  updateEmailConfiguration(
    @Body() newEmailConfiguration: EmailConfigurationDTO,
  ) {
    return this.updateConfiguration({
      email: newEmailConfiguration,
    });
  }
  @Put("/user")
  updateUserConfiguration(@Body() newUserConfiguration: UserConfigurationDTO) {
    return this.updateConfiguration({
      user: newUserConfiguration,
    });
  }
  @Put("/article")
  updateArticleConfiguration(
    @Body() newArticleConfiguration: ArticleConfigurationDTO,
  ) {
    return this.updateConfiguration({
      article: newArticleConfiguration,
    });
  }
  @Put("/rss")
  updateRSSConfiguration(@Body() newRSSConfiguration: RSSConfigurationDTO) {
    return this.updateConfiguration({
      rss: newRSSConfiguration,
    });
  }
  @Put("/twikoo")
  updateTwikooConfiguration(
    @Body() newTwikooConfiguration: TwikooConfigurationDTO,
  ) {
    return this.updateConfiguration({
      twikoo: newTwikooConfiguration,
    });
  }
  @Put("/tongji/baidu")
  updateBaiduTongjiConfigurations(
    @Body() newBaiduTongjiConfigurations: BaiduTongjiConfigurationDTO[],
  ) {
    return this.updateConfiguration({
      tongji: {
        baidu: newBaiduTongjiConfigurations,
      },
    });
  }
  @Put("/wechat")
  updateWechatConfiguration(newWechatConfiguration: WechatConfigurationDTO) {
    return this.updateConfiguration({
      wechat: newWechatConfiguration,
    });
  }
}

@Module({
  imports: [UserModule],
  providers: [AdminConfigurationService],
  controllers: [AdminConfigurationController],
})
export class AdminConfigurationModule {}
